/**
 * @file tiny_error.c
 * @brief 负责错误信息输出.
 * @author 张恒宣 
 * @LastEditTime 2025/4/06
 * 
 * MIT License
 *
 * Copyright (c) 2025 张恒宣 luckkeymail@163.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/*********************
 *      头文件
 *********************/
#include <stdio.h>
#include <stdint.h>
#include "tiny_thread.h"
extern tiny_thread_t *cur_running_thread;
void ListFalutInfo_Handler(uint32_t* sp)
{
		extern uint32_t Image$$ER_IROM1$$Base;
		extern uint32_t Image$$ER_IROM1$$Length;
		// 栈顶地址（由启动文件定义）
		extern uint32_t __initial_sp;  
	
		printf("[no rtos]ListFalutInfo_Handler: sp = %p\r\n", sp);
		if (cur_running_thread)
		{
			printf("Now Thread: %s\r\n", cur_running_thread->name);
		}
		env_register_t* ptcp = (env_register_t*)sp;
		printf("r0  = 0x%x\r\n", ptcp->r0);
		printf("r1  = 0x%x\r\n", ptcp->r1);
		printf("r2  = 0x%x\r\n", ptcp->r2);
		printf("r3  = 0x%x\r\n", ptcp->r3);
		printf("r12 = 0x%x\r\n", ptcp->r12);
		printf("LR  = 0x%x\r\n", ptcp->lr);
		printf("return addr  = 0x%x\r\n", ptcp->pc); 
		printf("you can use command to get more info such as:\n\rarm-none-eabi-addr2line -p -f -e test.axf 0x%x ", ptcp->pc);
	
		sp += 8;
		do
		{
			if ((int)*sp >= (int)&Image$$ER_IROM1$$Base && (int)*sp < (int)&Image$$ER_IROM1$$Base + (int)&Image$$ER_IROM1$$Length)
			{
				uint32_t* pInstAddr = (uint32_t*)(*sp & ~(0x1));
				/* 
				 * 指令测试
					printf("0x%p : 0x%p\r\n", sp, pInstAddr);
					printf("inst : 0x%x\r\n", *(uint32_t*)pInstAddr);
					printf("last inst: inst : 0x%x\r\n", *(uint32_t*)(pInstAddr - 1));
				*/

				uint32_t inst = *(uint32_t*)(pInstAddr - 1);
				if ((inst & 0xf4) == 0xf4) // 粗略判断是否是BL指令
				{
					printf("0x%p ", pInstAddr - 1);
				}
			}
			
		}while((uint32_t)++sp < (uint32_t)&__initial_sp);
		
		printf("\r\nlist ok!\r\n");

}
void ThreadListFalutInfo_Handler(uint32_t* sp)
{
		extern uint32_t Image$$ER_IROM1$$Base;
		extern uint32_t Image$$ER_IROM1$$Length;
	
		printf("[tiny_rtos]ThreadListFalutInfo_Handler: sp = %p\r\n", sp);
	
		if (!cur_running_thread)
		{
			printf("can not find thread info...\r\n");
			return;
		}
		
		printf("Now Thread: %s\r\n", cur_running_thread->name);
		env_register_t* ptcp = (env_register_t*)sp;
		printf("r0  = 0x%x\r\n", ptcp->r0);
		printf("r1  = 0x%x\r\n", ptcp->r1);
		printf("r2  = 0x%x\r\n", ptcp->r2);
		printf("r3  = 0x%x\r\n", ptcp->r3);
		printf("r12 = 0x%x\r\n", ptcp->r12);
		printf("LR  = 0x%x\r\n", ptcp->lr);
		printf("return addr  = 0x%x\r\n", ptcp->pc); 
		printf("you can use command to get more info such as:\n\rarm-none-eabi-addr2line -p -f -e test.axf 0x%x ", ptcp->pc);
		
		sp += 8;
		do
		{
			if ((int)*sp >= (int)&Image$$ER_IROM1$$Base && (int)*sp < (int)&Image$$ER_IROM1$$Base + (int)&Image$$ER_IROM1$$Length)
			{
				uint32_t* pInstAddr = (uint32_t*)(*sp & ~(0x1));
				uint32_t inst = *(uint32_t*)(pInstAddr - 1);
				if ((inst & 0xf4) == 0xf4) // 粗略判断是否是BL指令
				{
					printf("0x%p ", pInstAddr - 1);
				}
			}
		}while((uint32_t)++sp < ((uint32_t)cur_running_thread->stack + cur_running_thread->statck_size));
		
		printf("\r\nlist ok!\r\n");
}

